/**
 * Copyright 2020 OPSLI 快速开发平台 https://www.opsli.com
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.opsli.modulars.business.pipelineStation.web;

import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson.JSONObject;
import io.reactivex.rxjava3.core.Completable;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.RegionUtil;
import org.opsli.api.web.business.pipelineStation.PipelineStationRestApi;
import org.opsli.api.wrapper.business.pipelineStation.PipelineStationModel;
import org.opsli.api.wrapper.business.routeStation.RouteStationModel;
import org.opsli.common.annotation.RequiresPermissionsCus;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.opsli.api.base.result.ResultVo;
import org.opsli.common.annotation.ApiRestController;
import org.opsli.common.annotation.EnableLog;
import org.opsli.core.base.controller.BaseRestController;
import org.opsli.core.persistence.Page;
import org.opsli.core.persistence.querybuilder.QueryBuilder;
import org.opsli.core.persistence.querybuilder.WebQueryBuilder;
import org.opsli.core.utils.*;
import org.opsli.modulars.business.app.web.CoordinatesConvertUtil;
import org.opsli.modulars.business.app.web.MapCordinatesVo;
import org.opsli.modulars.business.app.web.ZkUtils;
import org.opsli.modulars.business.patrolRouteRecord.entity.DailyInspectionReport;
import org.opsli.modulars.business.patrolRouteRecord.web.DailyInspectionReportController;
import org.opsli.modulars.business.pipelineLayout.entity.Pipeline;
import org.opsli.modulars.business.pipelineLayout.mapper.PipelineMapper;
import org.opsli.modulars.business.routeStation.entity.RouteStation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.activation.MimetypesFileTypeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.URL;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.*;

import org.opsli.modulars.business.pipelineStation.entity.PipelineStation;
import org.opsli.modulars.business.pipelineStation.service.IPipelineStationService;

/**
 * 管道路线对应点 Controller
 *
 * @author Ljc
 * @date 2021-11-25 13:50:20
 */
@Api(tags = PipelineStationRestApi.TITLE)
@Slf4j
@ApiRestController("/business/pipelineStation")
public class PipelineStationRestController extends BaseRestController<PipelineStation, PipelineStationModel, IPipelineStationService>
        implements PipelineStationRestApi {
    @Autowired
    PipelineMapper pipelineMapper;

    /**
     * 管道路线对应点 查一条
     * @param model 模型
     * @return ResultVo
     */
    @ApiOperation(value = "获得单条管道路线对应点", notes = "获得单条管道路线对应点 - ID")
    @RequiresPermissions("pipelinestation_select")
    @Override
    public ResultVo<PipelineStationModel> get(PipelineStationModel model) {
        // 如果系统内部调用 则直接查数据库
        if(model != null && model.getIzApi() != null && model.getIzApi()){
            model = IService.get(model);
        }
        return ResultVo.success(model);
    }

    @Override
    public ResultVo<List<Map>> findLast(String routeid) {
        //根据管道id获取种类信息
        Pipeline pipeline= pipelineMapper.getFindStation(routeid);
        List<Map> list=new ArrayList();
        List<PipelineStation> pipelineStations=IService.findList(routeid);
        if(pipelineStations!=null&&pipelineStations.size()>0){
            for(PipelineStation pipelineStation:pipelineStations){
                Map map=new HashMap();
//                MapCordinatesVo cordinatesVo=new MapCordinatesVo();
//                cordinatesVo.setLon(new BigDecimal(pipelineStation.getLongitude()));
//                cordinatesVo.setLat(new BigDecimal(pipelineStation.getDimension()));
//                cordinatesVo= CoordinatesConvertUtil.bd_encrypt(cordinatesVo);
//                map.put("lt",cordinatesVo.getLon());//纬度
//                map.put("ln",cordinatesVo.getLat());//经度
//                map.put("lo",pipelineStation.getLocation());

                map.put("lt",pipelineStation.getLongitude());//纬度
                map.put("ln",pipelineStation.getDimension());//经度
                map.put("lo",pipelineStation.getLocation()); //点的位置信息描述
                map.put("pressureType",pipeline.getPressureType());//管道种类 /** 压力种类1低压2中压3高压 */
                map.put("pipedepth",pipelineStation.getPipedepth());//管埋深度
                map.put("mileage",pipelineStation.getMileage());//里程
                map.put("elevation",pipelineStation.getElevation());//高程
                map.put("remark",pipelineStation.getRemark());//管道周边信息
                map.put("texture",pipelineStation.getTexture());//材质
                list.add(map);
            }
        }
        return ResultVo.success(list);
    }

    /**
    * 管道路线对应点 查询分页
    * @param pageNo 当前页
    * @param pageSize 每页条数
    * @param request request
    * @return ResultVo
    */
    @ApiOperation(value = "获得分页数据", notes = "获得分页数据 - 查询构造器")
    @RequiresPermissions("pipelinelayout_b")
    @Override
    public ResultVo<?> findPage(Integer pageNo, Integer pageSize, HttpServletRequest request) {

        QueryBuilder<PipelineStation> queryBuilder = new WebQueryBuilder<>(entityClazz, request.getParameterMap());
        Page<PipelineStation, PipelineStationModel> page = new Page<>(pageNo, pageSize);
        page.setQueryWrapper(queryBuilder.build());
        page = IService.findPage(page);

        return ResultVo.success(page.getPageData());
    }

    /**
    * 管道路线对应点 新增
    * @param model 模型
    * @return ResultVo
    */
    @ApiOperation(value = "新增管道路线对应点数据", notes = "新增管道路线对应点数据")
//    @RequiresPermissions("pipelinestation_insert")
    @EnableLog
    @Override
    public ResultVo<?> insert(PipelineStationModel model) {
        //转坐标系，因坐标系的不同 导致地图里有偏差 所以入库时转换
        try {
//            MapCordinatesVo cordinatesVo=new MapCordinatesVo();
//            cordinatesVo.setLon(new BigDecimal(model.getLongitude()));
//            cordinatesVo.setLat(new BigDecimal(model.getDimension()));
//            cordinatesVo= CoordinatesConvertUtil.gd_decrypt(cordinatesVo);
//            model.setLongitude(cordinatesVo.getLon().toString());
//            model.setDimension(cordinatesVo.getLat().toString());

            model.setLongitude(model.getLongitude());
            model.setDimension(model.getDimension());
        }catch (Exception e){

        }
        // 调用新增方法
        IService.insert(model);
        return ResultVo.success("新增管道路线对应点成功");
    }

    /**
     * 管道路线对应点 修改
     * @param model 模型
     * @return ResultVo
     */
    @ApiOperation(value = "修改管道路线对应点数据", notes = "修改管道路线对应点数据")
//    @RequiresPermissions("pipelinestation_update")
    @EnableLog
    @Override
    public ResultVo<?> update(PipelineStationModel model) {
        PipelineStationModel old=IService.get(model.getId());
        if(ZkUtils.isNotBlank(model.getDimension())&&ZkUtils.isNotBlank(model.getLongitude())){
            if(!model.getDimension().equals(old.getDimension())||!model.getLongitude().equals(old.getLongitude())){
//                MapCordinatesVo cordinatesVo=new MapCordinatesVo();
//                cordinatesVo.setLon(new BigDecimal(model.getLongitude()));
//                cordinatesVo.setLat(new BigDecimal(model.getDimension()));
//                cordinatesVo= CoordinatesConvertUtil.gd_decrypt(cordinatesVo);
//                model.setLongitude(cordinatesVo.getLon().toString());
//                model.setDimension(cordinatesVo.getLat().toString());
                model.setLongitude(model.getLongitude());
                model.setDimension(model.getDimension());
            }
        }
        // 调用修改方法
        IService.update(model);
        return ResultVo.success("修改管道路线对应点成功");
    }


    /**
     * 管道路线对应点 删除
     * @param id ID
     * @return ResultVo
     */
    @ApiOperation(value = "删除管道路线对应点数据", notes = "删除管道路线对应点数据")
//    @RequiresPermissions("pipelinestation_update")
    @EnableLog
    @Override
    public ResultVo<?> del(String id){
        IService.delete(id);
        return ResultVo.success("删除管道路线对应点成功");
    }

    /**
     * 管道路线对应点 批量删除
     * @param ids ID 数组
     * @return ResultVo
     */
    @ApiOperation(value = "批量删除管道路线对应点数据", notes = "批量删除管道路线对应点数据")
//    @RequiresPermissions("pipelinestation_update")
    @EnableLog
    @Override
    public ResultVo<?> delAll(String ids){
        String[] idArray = Convert.toStrArray(ids);
        IService.deleteAll(idArray);
        return ResultVo.success("批量删除管道路线对应点成功");
    }


    /**
     * 管道路线对应点 Excel 导出
     * 注：这里 RequiresPermissionsCus 引入的是 自定义鉴权注解
     *
     * 导出时，Token认证和方法权限认证 全部都由自定义完成
     * 因为在 导出不成功时，需要推送错误信息，
     * 前端直接走下载流，当失败时无法获得失败信息，即使前后端换一种方式后端推送二进制文件前端再次解析也是最少2倍的耗时
     * ，且如果数据量过大，前端进行渲染时直接会把浏览器卡死
     * 而直接开启socket接口推送显然是太过浪费资源了，所以目前采用Java最原始的手段
     * response 推送 javascript代码 alert 提示报错信息
     *
     * @param request request
     * @param response response
     */
    @ApiOperation(value = "导出Excel", notes = "导出Excel")
    @RequiresPermissionsCus("pipelinestation_export")
    @EnableLog
    @Override
    public void exportExcel(HttpServletRequest request, HttpServletResponse response) {
        // 当前方法
        Method method = ReflectUtil.getMethodByName(this.getClass(), "exportExcel");
        QueryBuilder<PipelineStation> queryBuilder = new WebQueryBuilder<>(entityClazz, request.getParameterMap());
        super.excelExport(PipelineStationRestApi.SUB_TITLE, queryBuilder.build(), response, method);
    }
    /**
     *
     * 根据经纬度获取详细信息  百度地图
     */

    public  Map<String,Object> getcitydetailbyjingwei(double jing ,double wei)
    {
        Map<String, Object> map = null;
        Map<String, Object> aa = null;
        String url = "http://api.map.baidu.com/reverse_geocoding/v3/?"
                + "ak=LLLdGDRgc84g8e9WKf1RFchoopReUUT1&output=json&coordtype=wgs84ll&location="
                +wei+","+jing;
        try {
            HttpClient client = HttpClientBuilder.create().build();//构建一个Client
            HttpGet get = new HttpGet(url.toString());    //构建一个GET请求
            HttpResponse response = client.execute(get);//提交GET请求
            HttpEntity result = response.getEntity();//拿到返回的HttpResponse的"实体"
            String content = EntityUtils.toString(result);
//            JSONObject res = JSONObject.fromObject(content);

            JSONObject jsonObject = JSONObject.parseObject(content);

            Object re = jsonObject.get("result");
             aa = JSONObject.parseObject(JSONObject.toJSONString(re), Map.class);

//            map = JsonUtil.parseJSON2Map(res); //通过下面的函数将json转化为map
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("获取地址失败");
        }
        return aa;
    }


    /**
     * 管道路线对应点 Excel 导入
     * 注：这里 RequiresPermissions 引入的是 Shiro原生鉴权注解
     * @param request 文件流 request
     * @return ResultVo
     */
    @ApiOperation(value = "导入Excel", notes = "导入Excel")
    @RequiresPermissions("pipelinestation_import")
    @EnableLog
    @Override
    public ResultVo<?> importExcel(MultipartHttpServletRequest request) {

        MultipartFile file = request.getFile("file");

        //获取表名 根据表名获取事实表的id
        String bm = file.getOriginalFilename();

        //取出表格里的数据
        InputStream inputStream = null;

        try {
            //1.获取文件的输入流
            inputStream = file.getInputStream();
            //2.获取Excel工作簿对象
            HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
            //3.获取Excel工作表对象 因为此时只有一个工作表对象所以取第一个对象即可
            //如果是多个工作表对象 可以通过如下方式获取后进行遍历
            int numberOfSheets = workbook.getNumberOfSheets();
            HSSFSheet sheetAt = workbook.getSheetAt(0); //取出首页数据

            System.out.println("总行数："+(sheetAt.getLastRowNum()+1));
            int rows=sheetAt.getLastRowNum()+1;

            String routeid = sheetAt.getSheetName();//页名名称  管道id
            ArrayList<PipelineStationModel> arrayList=new ArrayList<>();

            //先取出首页表格的数据  从第二行开始读取数据
            for (int i = 0; i < rows; i++) {
                if(i>=1){
                    System.out.println(i);
                    HSSFRow row= sheetAt.getRow(i);
                    int number = row.getPhysicalNumberOfCells();

                    PipelineStationModel pipelineStation=new PipelineStationModel();
                    pipelineStation.setRouteid(routeid);//管道ID
                    pipelineStation.setSort(String.valueOf(i));//排序

                    HSSFCell  stationname = row.getCell(0);
                    if(null != stationname){
                        stationname.setCellType(CellType.STRING); //设置单元格类型
                        pipelineStation.setStationname(stationname.getStringCellValue());//点名
                    }
                    HSSFCell  mileage = row.getCell(1);
                    if(null != mileage){
                        mileage.setCellType(CellType.STRING); //设置单元格类型
                        pipelineStation.setMileage(mileage.getStringCellValue());//里程
                    }
                    HSSFCell  elevation = row.getCell(2);
                    if(null != elevation){
                        elevation.setCellType(CellType.STRING); //设置单元格类型
                        pipelineStation.setElevation(elevation.getStringCellValue());//高程
                    }
                    HSSFCell  coding = row.getCell(3);
                    if(null != coding){
                        coding.setCellType(CellType.STRING); //设置单元格类型
                        pipelineStation.setCoding(coding.getStringCellValue());//编码
                    }
                    HSSFCell  pipedepth = row.getCell(4);
                    if(null != pipedepth){
                        pipedepth.setCellType(CellType.STRING); //设置单元格类型
                        pipelineStation.setPipedepth(pipedepth.getStringCellValue());//埋深（m)
                    }
                    HSSFCell  remark = row.getCell(5);
                    if(null != remark){
                        remark.setCellType(CellType.STRING); //设置单元格类型
                        pipelineStation.setRemark(remark.getStringCellValue());//备注
                    }
                    HSSFCell  dimension = row.getCell(6);
                    if(null !=dimension){
                        dimension.setCellType(CellType.STRING); //设置单元格类型
                        pipelineStation.setDimension(dimension.getStringCellValue());//纬度
                    }
                    HSSFCell  longitude = row.getCell(7);
                    if(null !=longitude) {
                        longitude.setCellType(CellType.STRING); //设置单元格类型
                        pipelineStation.setLongitude(longitude.getStringCellValue());//经度
                    }
                     HSSFCell  texture = row.getCell(8);
                     if(null !=texture){
                         texture.setCellType(CellType.STRING); //设置单元格类型
                         pipelineStation.setTexture(texture.getStringCellValue());//材质
                     }
                    //WGS84 转 BD09
                    if(null !=pipelineStation.getDimension() || null != pipelineStation.getLongitude()){
                        Map map=new HashMap();
                        map.put("lng",pipelineStation.getLongitude());
                        map.put("lat",pipelineStation.getDimension());
                        Map lnmap= WGS84Util.wgs84ToBd09(map);
                        String lng= lnmap.get("lng").toString();
                        String lat= lnmap.get("lat").toString();
                        pipelineStation.setLongitude(lng);//经度
                        pipelineStation.setDimension(lat);//纬度
                    }



//                    * 位置描述 location
//                    Map<String,Object> map= this.getcitydetailbyjingwei(Double.parseDouble(pipelineStation.getLongitude()),Double.parseDouble(pipelineStation.getDimension()));
//                    Object location=map.get("formatted_address");
//                        pipelineStation.setLocation(location.toString());
                    arrayList.add(pipelineStation);
                }
            }
            //把表中数据录入到数据库

           System.out.println(arrayList.size());
            IService.insertBatch(arrayList);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new ResultVo<>();
    }

    /**
     * 管道路线对应点 Excel 下载导入模版
     * 注：这里 RequiresPermissionsCus 引入的是 自定义鉴权注解
     * @param response response
     */
    @ApiOperation(value = "导出Excel模版", notes = "导出Excel模版")
    @RequiresPermissionsCus("pipelinestation_import")
    @Override
    public void importTemplate(HttpServletResponse response,HttpServletRequest request) {

        String ji= request.getQueryString();
        String cs="";
        try {
            cs= URLDecoder.decode(request.getQueryString(),"utf-8");//将中文转码
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        //先获取最后一个  - 所在的位置
        int index = cs.lastIndexOf("&");
        //获取从0到最后一个 - 之间的字符
        String ss = cs.substring(0, index);

        String str1 = ss.substring(0, cs.indexOf("="));
        String str2=ss.substring(str1.length()+1);

        Pipeline pipeline= pipelineMapper.getFindStation(str2);

        String titleName = pipeline.getPipelineRoadAme();
        //输出文件流
        OutputStream output = null;
        try {
            output = response.getOutputStream();
            response.reset();
            response.setHeader("Content-Disposition",
                    "attchement;filename=" + new String((titleName + ".xls").getBytes("gb2312"), "ISO8859-1"));
            response.setContentType("application/msexcel");
        } catch (IOException e) {
            e.printStackTrace();
        }
        HSSFWorkbook book = null;
        try {
            book = new HSSFWorkbook(this.getExcelFile(str2));
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
        try {
            book.write(output);
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
        try {
            output.flush();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }
        try {
            output.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        }

    }

    //导出Excel样式
    private HSSFWorkbook workbook;
    private HSSFSheet sheet;

    public InputStream getExcelFile( String titleName) throws IOException {

        //创建sheet
        workbook = new HSSFWorkbook();
        sheet = workbook.createSheet(titleName);
        //字体样式
        HSSFFont font = workbook.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 16);// 字体大小
        //字体加粗样式
        HSSFFont font0 = workbook.createFont();
        font0.setFontName("宋体");
        font0.setFontHeightInPoints((short) 20);
//        font0.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        //通用字体样式
        HSSFCellStyle cs0 = workbook.createCellStyle();//创建第一行样式
//        cs0.setAlignment((short) 2);// 左右居中2 居右3 默认居左
        cs0.setFont(font);
//        cs0.setVerticalAlignment(HSSFCellStyle.VERTICAL_CENTER);// 上下居中1
//        cs0.setBorderBottom(HSSFCellStyle.BORDER_THIN);
//        cs0.setBorderLeft(HSSFCellStyle.BORDER_THIN);
//        cs0.setBorderRight(HSSFCellStyle.BORDER_THIN);
//        cs0.setBorderTop(HSSFCellStyle.BORDER_THIN);

        //小区名称
        //exRow1
        HSSFRow h1 = sheet.createRow(0);//获取第1行
        HSSFCell c1 = h1.createCell(0);//点名
        c1.setCellValue("点名");
        c1.setCellStyle(cs0);
        HSSFCell c2 = h1.createCell(1);//里程
        c2.setCellValue("里程");
        c2.setCellStyle(cs0);
        HSSFCell c3 = h1.createCell(2);//高程
        c3.setCellValue("高程");
        c3.setCellStyle(cs0);
        HSSFCell c4 = h1.createCell(3);//编码
        c4.setCellValue("编码");
        c4.setCellStyle(cs0);
        HSSFCell c5 = h1.createCell(4);//埋深（m)
        c5.setCellValue("埋深（m)");
        c5.setCellStyle(cs0);
        HSSFCell c6 = h1.createCell(5);//备注
        c6.setCellValue("备注");
        c6.setCellStyle(cs0);
        HSSFCell c7 = h1.createCell(6);//纬度
        c7.setCellValue("纬度");
        c7.setCellStyle(cs0);
        HSSFCell c8 = h1.createCell(7);//经度
        c8.setCellValue("经度");
        c8.setCellStyle(cs0);
        HSSFCell c9 = h1.createCell(8);//材质
        c9.setCellValue("材质");
        c9.setCellStyle(cs0);


        for (int s = 0; s <= 8; s++) {
            sheet.setColumnWidth(s, 5000);
        }

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        workbook.write(baos);
        byte[] ba = baos.toByteArray();
        ByteArrayInputStream bais = new ByteArrayInputStream(ba);
        return bais;
    }

}